﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using WorkItemAnalyser.Core.Assertions;

namespace WorkItemAnalyser.Core.Parsers
{
    public class TextScenarioParser
    {
        private const string ScenarioQueryGrammer =
            @"for each (?<workItemType>.*) in (?<project>.*)";

        private const string ScenarioFilterGrammer =
            @"the (?<field>.*) field is (?<value>.*)";
        //                                        @"the (?<field>.*) should be (?<value>.*)";


        public Scenario ParseScenario(string scenarioText)
        {
            if (string.IsNullOrWhiteSpace(scenarioText)) return null;

            var scenarios = ParseScenarioPart<Scenario>(scenarioText, ScenarioQueryGrammer,
                                                       (match) =>
                                                       new Scenario(match.Groups["workItemType"].ToString().Trim(),
                                                                    match.Groups["project"].ToString().Trim()));

            if (scenarios == null) return null;

            var scenario = scenarios.FirstOrDefault();

            var filters = ParseScenarioPart<IAssertion>(scenarioText, ScenarioFilterGrammer,
                (match) => new FieldAssertion(match.Groups["field"].ToString(), match.Groups["value"].ToString().Trim()));

            foreach (var filter in filters)
            {
                scenario.AddFilter(filter);
            }

            return scenario;
        }

        private IEnumerable<TPartType> ParseScenarioPart<TPartType>(string scenarioText, string grammar, Func<Match, TPartType> matchProcessor)
            where TPartType : class
        {
            var expression = new Regex(grammar, RegexOptions.IgnoreCase);
            var matches = expression.Matches(scenarioText);

            if (matches.Count < 1) return null;

            var returnCollection = new Collection<TPartType>();

            foreach (Match match in matches)
            {
                returnCollection.Add(matchProcessor(match));
            }

            return returnCollection;
        }
    }
}
